package com.xq.shop.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xq.shop.config.FileConfig;
import com.xq.shop.config.Redis;
import com.xq.shop.dao.domain.entity.*;
import com.xq.shop.dao.mapper.ColumnMapper;
import com.xq.shop.dto.EditColumnDto;
import com.xq.shop.dto.IntegerDto;
import com.xq.shop.dto.QueryDto;
import com.xq.shop.service.IColumnCategoryService;
import com.xq.shop.service.IColumnService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xq.shop.service.IFileService;
import com.xq.shop.service.IGoodsTypeService;
import com.xq.shop.utils.MyConstants;
import com.xq.shop.vo.ColumnVo;
import com.xq.shop.vo.GoodsTypeVo;
import enums.DataStatus;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import utils.BasePage;

import javax.annotation.Resource;
import java.util.*;

/**
 * <p>
 * 栏目表 服务实现类
 * </p>
 *
 * @author gaoxiaojin
 * @since 2024-07-22
 */
@Service
public class ColumnServiceImpl extends ServiceImpl<ColumnMapper, Column> implements IColumnService {

    private final IColumnCategoryService columnCategoryService;
    private final IGoodsTypeService goodsTypeService;
    private final IFileService fileService;

    @Resource
    private Redis redis;

    @Resource
    private FileConfig fileConfig;

    @Autowired
    public ColumnServiceImpl(IColumnCategoryService columnCategoryService, IGoodsTypeService goodsTypeService, IFileService fileService) {
        this.columnCategoryService = columnCategoryService;
        this.goodsTypeService = goodsTypeService;
        this.fileService = fileService;
    }

    @Override
    public BasePage<ColumnVo> pageQuery(QueryDto dto) {
        LambdaQueryWrapper<Column> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Column::getStatus, DataStatus.NORMAL.getCode());
        if (Objects.nonNull(dto.getContent())) {
            wrapper.like(Column::getName, dto.getContent());
        }
        wrapper.orderByDesc(Column::getId);
        IPage<Column> page = page(new Page<>(dto.getPage(), dto.getLimit()), wrapper);
        List<Column> columnList = page.getRecords();
        if (columnList.isEmpty()) {
          return new BasePage<ColumnVo>().initPage(dto.getPage(), dto.getLimit(), page.getTotal(), page.getPages(), new ArrayList<>());
        }
        List<ColumnVo> voList = beanToVo(columnList);
        return new BasePage<ColumnVo>().initPage(dto.getPage(), dto.getLimit(), page.getTotal(), page.getPages(), voList);
    }

    private List<ColumnVo> beanToVo(List<Column> columnList) {
        List<ColumnVo> voList = new ArrayList<>();
        columnList.forEach(column -> {
            ColumnVo vo = new ColumnVo();
            BeanUtils.copyProperties(column, vo);
            if (Objects.nonNull(column.getImageId())) {
                MyFile file = fileService.getById(column.getImageId());
                vo.setImageurl(fileConfig.montageUrl(file.getUrl()));
            }
            LambdaQueryWrapper<ColumnCategory> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(ColumnCategory::getColumnId, column.getId());
            List<Object> idList = columnCategoryService.listObjs(wrapper.select(ColumnCategory::getCategoryId));
            LambdaQueryWrapper<GoodsType> goodsTypeWrapper = new LambdaQueryWrapper<>();
            goodsTypeWrapper.eq(GoodsType::getStatus, DataStatus.NORMAL.getCode());
            goodsTypeWrapper.in(GoodsType::getId, idList);
            List<GoodsType> goodsTypeList = goodsTypeService.list(goodsTypeWrapper);
            List<GoodsTypeVo> goodsTypeVoList = new ArrayList<>();
            List<String> str = new ArrayList<>();
            goodsTypeList.forEach(goodsType -> {
                if (goodsType.getLevel() == 3) {
                    str.add(goodsType.getDisplayName());
                }
                GoodsTypeVo goodsTypeVo = new GoodsTypeVo();
                BeanUtils.copyProperties(goodsType, goodsTypeVo);
                goodsTypeVoList.add(goodsTypeVo);
            });
            vo.setCategoryStr(String.join(",", str));
            vo.setCategoryTree(MyConstants.buildGoodsTypeTree(goodsTypeVoList));
            voList.add(vo);
        });
        return voList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editColumn(EditColumnDto dto, Integer userId) {

        Column column = new Column();
        if (dto.getId().equals(0)) {
            column.setCreateUser(userId);
            BeanUtils.copyProperties(dto, column);
            save(column);
        } else {
            column = getById(dto.getId());
            BeanUtils.copyProperties(dto, column);
            column.setUpdateUser(userId);
            Map<String, Object> map = new HashMap<>(8);
            map.put("column_id", dto.getId());
            columnCategoryService.removeByMap(map);
            updateById(column);
        }
        List<ColumnCategory> columnCategoryList = new ArrayList<>();
        Column finalColumn = column;
        dto.getCategoryIdList().forEach(id -> {
            ColumnCategory columnCategory = new ColumnCategory();
            columnCategory.setColumnId(finalColumn.getId());
            columnCategory.setCategoryId(id);
            columnCategoryList.add(columnCategory);
        });
        columnCategoryService.saveBatch(columnCategoryList);
        redis.remove("column");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeColumn(IntegerDto dto, Integer id) {
        Column column = getById(dto.getValue());
        if (Objects.nonNull(column)) {
            column.setStatus(DataStatus.INVALID.getCode());
            column.setUpdateUser(id);
            updateById(column);
        }
        Map<String, Object> map = new HashMap<>(8);
        map.put("column_id", dto.getValue());
        columnCategoryService.removeByMap(map);
        redis.remove("column");
    }
}
